#pragma once 
#include<iostream>
#include <arpa/inet.h>
#include <sys/types.h>          
#include <sys/socket.h>
#include <functional>
#include "dict.hpp"
#include "nocopy.hpp"
#include "InetAddr.hpp"
#include"log.hpp"
using namespace std;
using func_t = function<std::string(std::string)>;
class Server:public nocopy
{
public:
	Server(func_t func,uint16_t localport)
		:_func(func),_localport(localport),_status(false),_sockfd(-1)
	{};
	 void init()//创建addr地址并与socket文件绑定
	 {
		_sockfd = socket(AF_INET,SOCK_DGRAM,0);
		if(_sockfd<0)
		{
			LOG(FATAL,"server socket create err\n");
			exit(1);
		};
		struct sockaddr_in localaddr;
		memset(&localaddr,0,sizeof(localaddr));
		localaddr.sin_family =AF_INET;
		localaddr.sin_port=htons(_localport);
		localaddr.sin_addr.s_addr =INADDR_ANY;
		int n =bind(_sockfd,reinterpret_cast<struct sockaddr*>(&localaddr),sizeof(localaddr));
		if (n < 0)
       	 	{
            		LOG(FATAL, "server bind error\n");
      		      exit(2);
       		 }
       		 LOG(DEBUG, "server init success\n");
	 };
	 void start()//接受信息并发送信息
	 {
		 _status =true;
		 char buffer[1024];
		 while(_status)
		 {
		 	struct sockaddr_in peer;
			socklen_t len =sizeof(peer);
			int n =recvfrom(_sockfd,buffer,sizeof(buffer)-1,0,reinterpret_cast<struct sockaddr*>(&peer),&len);
			if(n>0)
			{
				buffer[n] = 0;
				InetAddr inetaddr(peer);
				LOG(DEBUG,"receive [%s : %d]#%s\n",inetaddr.Ip().c_str(),inetaddr.Port(),buffer);
				//std::string echo ="[udp server echo]#";
				//echo +=buffer;
				std::string result = _func(buffer);

				sendto(_sockfd,result.c_str(),result.size(),0,reinterpret_cast<struct sockaddr*>(&peer),len);

			}
			else
			{
				LOG(DEBUG,"recvfrom err\n");
			}

		 };

	 };
	~Server()
	{
		if(_sockfd>0)
		close(_sockfd);
	};
private:
	bool _status;
	int _sockfd;
	uint16_t _localport;
	func_t _func;
};

